package com.zbkj.front.service.user.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zbkj.dal.base.enums.*;
import com.zbkj.dal.common.exception.CrmebException;
import com.zbkj.dal.common.utils.CrmebDateUtil;
import com.zbkj.dal.dao.*;
import com.zbkj.dal.entity.fund.UserFundAccount;
import com.zbkj.dal.entity.merchant.Merchant;
import com.zbkj.dal.entity.merchant.MerchantEmployee;
import com.zbkj.dal.entity.system.SystemUserLevel;
import com.zbkj.dal.entity.user.*;
import com.zbkj.dal.feign.client.WeWorkFeignClient;
import com.zbkj.dal.token.FrontTokenComponent;
import com.zbkj.front.service.user.UserV2Service;
import com.zbkj.service.manager.*;
import com.zbkj.service.model.front.req.user.BindBankcardReq;
import com.zbkj.service.model.front.req.user.UnbindBankReq;
import com.zbkj.service.model.front.vo.CustomerServiceVO;
import com.zbkj.service.model.front.vo.fund.UserQuotaVO;
import com.zbkj.service.model.front.vo.user.BankInfoVO;
import com.zbkj.service.model.front.vo.user.UserInfoVO;
import com.zbkj.service.model.front.vo.user.UserLevelRecordVO;
import com.zbkj.service.model.vo.ArriveStoreAddressVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
@Service
public class UserV2ServiceImpl implements UserV2Service {

    @Resource
    private UserDao userDao;

    @Resource
    private MerchantDao merchantDao;

    @Resource
    private EmployeeDao employeeDao;

    @Resource
    private UserManager userManager;

    @Resource
    private FundManager fundManager;

    @Resource
    private QuotaManager quotaManager;

    @Resource
    private EmployeeManager employeeManager;

    @Resource
    private WeWorkFeignClient weWorkFeignClient;

    @Resource
    private EmployeeAccountDao employeeAccountDao;

    @Resource
    private FrontTokenComponent frontTokenComponent;

    @Resource
    private UserActivityRecordDao userActivityRecordDao;

    @Resource
    private MerchantManager merchantManager;

    @Value("${customer.service.default-merchant-id}")
    private Integer defaultMerchantId;

    @Value("${image.default.logo}")
    private String defaultLogo;

    @Override
    public UserInfoVO memberInfo() {
        Integer userId = frontTokenComponent.userId();
        User user = userDao.selectById(userId);
        if (Objects.isNull(user)) {
            log.error("未查询到用户id为{}的用户信息", userId);
            throw new CrmebException("用户信息异常，请稍后重试");
        }

        // 用户额度信息
        UserQuotaVO userQuotaVO = quotaManager.userQuota(userId);

        // 当前等级信息、下一等级信息
        SystemUserLevel nextLevel = quotaManager.nextLevelInfo(userQuotaVO.getLevelId());
        SystemUserLevel currentLevel = quotaManager.currentLevelInfo(userQuotaVO.getLevelId());

        UserFundAccount userFundAccount = fundManager.fundAccount(userId, FundAccountType.CRAB_ROE.name());

        EmployeeAccount employeeAccount = employeeManager.findEmployeeAccount(userId, AccountTypeEnums.FRONT.name());
        MerchantEmployee merchantEmployee = merchantManager.findEmployeeByUserId(userId);
        return UserInfoVO.generate(user, userQuotaVO, userFundAccount, currentLevel, nextLevel, employeeAccount, merchantEmployee);
    }

    @Override
    public BankInfoVO userBank() {
        Integer userId = frontTokenComponent.userId();
        UserBank userBank = userManager.userBankcard(userId);
        return BankInfoVO.generate(userBank);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addBankInfo(BindBankcardReq req) {
        Integer userId = frontTokenComponent.userId();
        UserBank userBank = userManager.userBankcard(userId);
        if (Objects.nonNull(userBank)) {
            throw new CrmebException("当前用户已绑定银行卡");
        }
        User user = userDao.selectById(userId);
        if (StringUtils.isNotBlank(user.getRealName())) {
            if (!StringUtils.equals(req.getAccountName(), user.getRealName())) {
                throw new CrmebException("绑定账户名称与用户名称不一致");
            }
        } else {
            LambdaUpdateWrapper<User> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.set(User::getRealName, req.getAccountName());
            updateWrapper.set(User::getUpdateTime, CrmebDateUtil.nowDateTime());
            updateWrapper.eq(User::getId, userId);
            userDao.update(null, updateWrapper);
        }

        userManager.bindUserBankcard(userId, req.getAccountName(), req.getBankCode(), req.getBankcardNo());
    }

    @Override
    public void unbindUserBank(UnbindBankReq req) {
        Integer userId = frontTokenComponent.userId();
        userManager.unbindBankcard(userId, req.getBankcardNo());
    }

    @Override
    public List<UserLevelRecordVO> userLevelRecord(Integer userId) {
        userId = Objects.isNull(userId) ? frontTokenComponent.userId() : userId;

        LambdaQueryWrapper<UserActivityRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserActivityRecord::getUserCode, String.valueOf(userId));
        wrapper.eq(UserActivityRecord::getActivityType, UserActivityTypeEnums.USER_LEVEL_UPGRADED.getCode());
        wrapper.eq(UserActivityRecord::getDeleted, BooleanEnums.FALSE.getCode());
        wrapper.orderByDesc(UserActivityRecord::getCreateTime);
        List<UserActivityRecord> userActivityRecords = userActivityRecordDao.selectList(wrapper);
        return userActivityRecords.stream().map(record -> {
            UserLevelRecordVO userLevelRecordVO = new UserLevelRecordVO();
            userLevelRecordVO.setCreateTime(record.getCreateTime());
            userLevelRecordVO.setDescription(record.getActivityDigest());
            return userLevelRecordVO;
        }).collect(Collectors.toList());
    }

    /**
     * 如果没有推荐人，查询一号店店长（没有推荐人，就不会有推荐店铺）
     * 如果直接推荐人是店长或动态店长，是直接推荐人
     * 如果直接推荐人不是，查询间接推荐人，如果间接推荐人是店长或动态店长，是间接推荐人
     * 如果直接推荐人、间接推荐人都不是，查询所属店铺店长
     */
    @Override
    public CustomerServiceVO customerService() {
        Integer userId = frontTokenComponent.userId();
        User customerServiceUser = customerServiceUser(userId);

        Employee employee = customerServiceEmployee(customerServiceUser.getId());
        if (Objects.isNull(employee)) {
            User user = no1MerchantManagerUser();
            employee = customerServiceEmployee(user.getId());
        }

        User user = userManager.findByUserId(userId);
        Integer spreadMerchantId = Objects.isNull(user.getSpreadMerchantId()) ? defaultMerchantId : user.getSpreadMerchantId();
        Merchant merchant = merchantDao.selectById(spreadMerchantId);


        String contractMeQrcode = weWorkFeignClient.createContractMeQrcode(employee.getWxWorkAccount());
        CustomerServiceVO customerServiceVO = new CustomerServiceVO();
        customerServiceVO.setAvatar(defaultLogo);
        customerServiceVO.setCustomerServiceName(employee.getRealName());
        customerServiceVO.setEmployeeNo(employee.getEmployeeNo());
        customerServiceVO.setQrcodeUrl(contractMeQrcode);
        if (Objects.nonNull(merchant)) {
            customerServiceVO.setStoreAddress(new ArriveStoreAddressVO(merchant));
        }

        return customerServiceVO;
    }

    private User customerServiceUser(Integer userId) {
        User user = userManager.findByUserId(userId);
        if (Objects.isNull(user.getSpreadUid())) {
            return this.spreadMerchantManagerUser(user);
        }
        User directSpreadUser = userManager.directSpreadUser(userId);
        if (Objects.isNull(directSpreadUser)) {
            return this.spreadMerchantManagerUser(user);
        }

        if (!StringUtils.equals(UserIdentityEnums.MEMBER.getCode(), directSpreadUser.getIdentity())) {
            return directSpreadUser;
        }

        User indirectSpreadUser = userManager.directSpreadUser(directSpreadUser.getId());
        if (Objects.isNull(indirectSpreadUser)) {
            return this.spreadMerchantManagerUser(user);
        }
        if (StringUtils.equals(UserIdentityEnums.MEMBER.getCode(), directSpreadUser.getIdentity())) {
            return spreadMerchantManagerUser(user);
        } else {
            return indirectSpreadUser;
        }
    }

    private User no1MerchantManagerUser() {
        Merchant merchant = merchantDao.selectById(defaultMerchantId);
        Integer managerUid = merchant.getManagerUid();
        return userManager.findByUserId(managerUid);
    }

    private User spreadMerchantManagerUser(User user) {
        if (Objects.isNull(user.getSpreadMerchantId())) {
            return no1MerchantManagerUser();
        }
        Merchant merchant = userManager.spreadMerchant(user.getSpreadMerchantId());
        if (Objects.isNull(merchant)) {
            return no1MerchantManagerUser();
        }
        if (Objects.isNull(merchant.getManagerUid())) {
            return no1MerchantManagerUser();
        }
        return userManager.findByUserId(merchant.getManagerUid());
    }

    private Employee customerServiceEmployee(Integer userId) {
        LambdaQueryWrapper<EmployeeAccount> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(EmployeeAccount::getAccountId, userId);
        wrapper.eq(EmployeeAccount::getAccountType, AccountTypeEnums.FRONT.name());
        EmployeeAccount employeeAccount = employeeAccountDao.selectOne(wrapper);
        if (Objects.isNull(employeeAccount)) {
            return null;
        }

        LambdaQueryWrapper<Employee> employeeWrapper = new LambdaQueryWrapper<>();
        employeeWrapper.eq(Employee::getEmployeeNo, employeeAccount.getEmployeeNo());
        employeeWrapper.eq(Employee::getStatus, EmployeeStatusEnum.ENABLE.getCode());
        employeeWrapper.eq(Employee::getDeleted, BooleanEnums.FALSE.getCode());
        return employeeDao.selectOne(employeeWrapper);
    }
}
